import configs
from fuzzywuzzy import fuzz
from template.singleton import Singleton
from utils import service_functions


class Numbers(Singleton):
    def __integer_decoder(self, list_number: list) -> int:
        # Преобразование списка разрядов числа в число
        # НЕ ЛЕЗЬ УБЪЁТ НАФИГ
        # Я туда не лезу без отладчика
        try:
            len_data = len(list_number)
            if len_data == 1:
                return list_number[0]
            index = 0
            value = 0
            while len_data > index:
                if len_data != 0:
                    if len_data - (index + 1) == 1 and len_data == 2:
                        value = value + list_number[index] * list_number[index + 1]
                        index += 1
                    elif len_data - (index + 1) == 0:
                        value = value + list_number[index]
                    # если пойдёт не пойёт list_number[x] < list_number[x + 1]
                    # and len_data - (x + 2) > 0
                    elif (
                        list_number[index] < list_number[index + 1]
                        and len_data - (index + 2) >= 0
                    ):
                        value = value + (list_number[index] * list_number[index + 1])
                        index += 1
                    # если пойдёт не пойёт то (x + 2) == 0 or x == 0 is not
                    # len_data == 2):
                    elif list_number[index] > list_number[index + 1] and (
                        len_data - (index + 2) == 0 or index == 0 != len_data == 2
                    ):
                        value = value + list_number[index] + list_number[index + 1]
                        index += 2
                    elif (
                        list_number[index]
                        > list_number[index + 1]
                        < list_number[index + 2]
                    ):
                        value = value + (
                            (list_number[index] + list_number[index + 1])
                            * list_number[index + 2]
                        )
                        index += 2
                    elif list_number[index] > list_number[index + 1] > list_number[
                        index + 2
                    ] and (len_data - (index + 3) == 0 or len_data == 3):
                        value = value + (
                            list_number[index]
                            + list_number[index + 1]
                            + list_number[index + 2]
                        )
                        index += 2
                    elif (
                        list_number[index]
                        > list_number[index + 1]
                        > list_number[index + 2]
                        < list_number[index + 3]
                    ):
                        value = value + (
                            (
                                list_number[index]
                                + list_number[index + 1]
                                + list_number[index + 2]
                            )
                            * list_number[index + 3]
                        )
                        index += 3
                index += 1
            return value
        except BaseException:
            raise
            # return int(float("inf"))

    def __convert_str_num_in_int_num(self, list_str_numbers: str):
        # Конверитрование список str чисел в список int чисел
        name_cmd_key_recognize = "interger"
        list_int_numbers = []
        for str_number in list_str_numbers.split():
            recognize_str = self.__recognize_str_numbers(
                str_number, name_cmd_key_recognize
            )
            try:
                number = configs.numbers[name_cmd_key_recognize][recognize_str]
            except BaseException:
                return recognize_str
            list_int_numbers.append(number)

        for x in list_int_numbers:
            if isinstance(x, str):
                self.__fractional_decoder(list_int_numbers)
            else:
                pass
        else:
            return self.__integer_decoder(list_int_numbers)

    def __fractional_decoder(self, mass: list) -> list:
        # Обработка дробных чисел
        point = 0
        list_frcat = []
        if len(mass) >= 4:
            for x in range(len(mass)):
                if mass[x] == ".":
                    list_frcat.append(self.__integer_decoder(mass[0:x]))
                    point = x
                elif point > 0:
                    list_frcat.append(
                        self.__integer_decoder(mass[point + 1 : len(mass) - 1])
                    )
                    point = 0

                elif len(mass) == x + 1:
                    list_frcat.append(mass[x])
            return list_frcat[0] + (
                list_frcat[1] * list_frcat[2] / (10 ** (len(str(list_frcat[1])) - 1))
            )
        elif len(mass) < 4:
            return []
        return list_frcat

    def __recognize_str_numbers(self, cmd: str, name_cmd_key: str):
        par = 100 / len(cmd)
        booleen = int(par + configs.PROBABILITY_CMD_CONST) <= 100
        mas = list(configs.numbers[name_cmd_key].keys())
        word = ""
        probMax = configs.probability_cmd
        if not booleen:
            return cmd
        elif booleen:
            for x in range(len(mas)):
                int_prob = fuzz.ratio(cmd, mas[x])
                service_functions.fuzz_word_cheek(mas[x])
                if int_prob >= configs.probability_cmd:
                    if int_prob > probMax:
                        probMax = int_prob
                        word = mas[x]
                    elif int_prob == probMax:
                        word = mas[x]

            return word

    def one_int_index_number(self, list_metka: list) -> int:
        # Достать Первый индек если он есть
        int_value = self.number_activation_label(list_metka)
        if len(int_value) != 0:
            if isinstance(int_value, int):
                return int_value[0]
            else:
                return -1
        else:
            return -1

    def cheek_number_error(self, list_number: list):
        # Проверка обибок речи
        error = False
        for x in range(len(list_number)):
            if len(list_number) == 1:
                return list_number
            elif x == 0:
                continue
            elif len(list_number) >= 2:
                if (
                    list_number[x - 1] > 10
                    and list_number[x - 1] < 20
                    and list_number[x] <= 10
                ):
                    # [11,1]
                    # [12 1]
                    # [15,9]
                    error = True
                elif (
                    list_number[x - 1] <= 10
                    and list_number[x] > 10
                    and list_number[x] < 20
                ):
                    # [11,1]
                    # [12 1]
                    # [15,9]
                    error = True
                elif list_number[x - 1] == list_number[x]:
                    error = True
                elif len(list_number) == 3 or 1:
                    # Исправить
                    if list_number[x - 1] > list_number[x] < list_number[x + 1]:
                        error = True
                    elif list_number[x - 1] > list_number[x] > list_number[x + 1]:
                        error = True
                else:
                    # Всё Правильно !!!
                    pass
        if error:
            return []
        elif not error:
            return list_number

    def number_activation_label(self, list_metka: list) -> list:
        try:
            list_int_str = []
            if not list_metka:
                return []
            elif len(list_metka) == 1:
                list_int_str.append(self.__convert_str_num_in_int_num(list_metka[0]))
            elif list_metka:
                for list_i in list_metka:
                    numbers = self.__convert_str_num_in_int_num(list_i)
                    if isinstance(numbers, str) or isinstance(numbers, list):
                        if len(numbers) == 0:
                            list_int_str.append(list_i)
                        elif len(numbers) == 1:
                            list_int_str.append(numbers[0])
                        else:
                            list_int_str.append(numbers)
                    elif isinstance(numbers, int):
                        list_int_str.append(numbers)
            return list_int_str
        except BaseException:
            return []
